/**
 * GroupService.java
 * Version 1.0.0
 * Created on 2019年1月15日
 */
package com.yincheng.oes.business.group.service;

import com.yincheng.oes.business.group.mapper.GroupMapper;
import com.yincheng.oes.business.group.mapper.GroupPaperMapper;
import com.yincheng.oes.business.group.mapper.GroupUserMapper;
import com.yincheng.oes.business.group.model.dto.GroupUserExcelTitleDTO;
import com.yincheng.oes.business.group.model.dto.GroupUserInfoDTO;
import com.yincheng.oes.business.group.model.dto.UserPaperExcelTitleDTO;
import com.yincheng.oes.business.group.model.dto.UserPaperResultDTO;
import com.yincheng.oes.business.group.model.entity.*;
import com.yincheng.oes.business.group.model.query.ExportGroupUsersReq;
import com.yincheng.oes.business.util.DigitalUtils;
import com.yincheng.oes.business.util.GroupUserExcelUtils;
import com.yincheng.oes.business.util.StringUtil;
import com.yincheng.oes.business.util.model.ExcelCell;
import com.yincheng.oes.business.util.model.ExcelStyle;
import com.yincheng.oes.sso.util.UserUtils;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author yangsy
 * @version 1.0.0
 * @since 创建时间：2019年1月15日
 * <p>
 * 功能描述：
 * <p>
 * 邮箱地址：446948434@qq.com
 */
@Service
public class GroupService {

    private static final Logger logger = LogManager.getLogger(GroupService.class);

    @Autowired
    private GroupMapper groupMapper;

    @Autowired
    private GroupUserMapper groupUserMapper;

    @Autowired
    private GroupPaperMapper groupPaperMapper;

    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy年MM月dd日 HH:dd");

    @Transactional
    public void saveGroup(GroupInfo groupInfo) {
        // 先判断是否为空
        Group group = groupInfo.getGroup();
        String groupId = group.getGroupId();
        Group g = groupMapper.selectByPrimaryKey(groupId);
        if (g == null) {
            group.setCreateTime(new Date());
            group.setValid("1");
            group.setCreateUserId(UserUtils.getUser().getUserId());
            groupMapper.insert(group);
        } else {
            groupMapper.update(group);
        }
        List<GroupUser> groupUsers = groupInfo.getGroupUsers();
        if (CollectionUtils.isNotEmpty(groupUsers)) {
            groupUserMapper.deleteByGroupId(groupId);
            int order = 1;
            for (GroupUser groupUser : groupUsers) {
                groupUser.setCreateTime(new Date());
                groupUser.setGroupUserId(UUID.randomUUID().toString());
                groupUser.setValid("1");
                groupUser.setOrderNum(order);
                order++;
            }
            groupUserMapper.batchInsert(groupUsers);
        }
    }

    public GroupInfo getGroupInfo(String groupId) {
        GroupInfo groupInfo = new GroupInfo();
        Group group = groupMapper.selectByPrimaryKey(groupId);
        if (group == null) {
            group = new Group();
            group.setGroupId(groupId);
            group.setCreateTime(new Date());
            group.setCreateUserId(UserUtils.getUser().getUserId());
            group.setCreateUserName(UserUtils.getUser().getUserName());
            groupInfo.setGroup(group);
            return groupInfo;
        }

        groupInfo.setGroup(group);
        List<GroupUser> list = groupUserMapper.selectByGroupId(groupId);
        groupInfo.setGroupUsers(list);
        return groupInfo;
    }

    /**
     * 将试卷推送给班级集合
     *
     * @param paperId  paperId
     * @param groupIds groupIds
     */
    @Transactional
    public void pushPaperToGroups(String paperId, String groupIds) {
        String[] groupIdArray = groupIds.split(",");
        for (String groupId : groupIdArray) {
            GroupPaper groupPaper = groupPaperMapper.selectByPaperIdAndGroupId(paperId, groupId);
            if (groupPaper == null) {
                groupPaper = new GroupPaper();
                groupPaper.setCreateTime(new Date());
                groupPaper.setCreateUserId(UserUtils.getUser().getUserId());
                groupPaper.setGroupId(groupId);
                groupPaper.setGroupPaperId(UUID.randomUUID().toString());
                groupPaper.setPaperId(paperId);
                groupPaper.setValid("1");
                groupPaperMapper.insert(groupPaper);
            }
        }
    }

    /**
     * 构建导出班级学员信息excel的列名信息
     *
     * @param req ExportGroupUsersReq
     * @return GroupUserExcelTitleDTO
     */
    private GroupUserExcelTitleDTO buildGroupUserExcelTitle(ExportGroupUsersReq req) {
        GroupUserExcelTitleDTO groupUserExcelTitle = new GroupUserExcelTitleDTO();
        List<UserPaperExcelTitleDTO> userPaperExcelTitleList = new ArrayList<>();
        List<ExportGroupPaperDO> exportGroupPaperDOS = groupPaperMapper.selectExportGroupPapersByGroupId(req.getGroupId());
        logger.debug("query exportGroupPaperDOS are {}", exportGroupPaperDOS);
        if (CollectionUtils.isEmpty(exportGroupPaperDOS)) {
            groupUserExcelTitle.setUserPaperExcelTitleList(userPaperExcelTitleList);
            return groupUserExcelTitle;
        }

        userPaperExcelTitleList = exportGroupPaperDOS.stream().filter(Objects::nonNull).map(exportGroupPaperDO -> {
            UserPaperExcelTitleDTO userPaperExcelTitle = new UserPaperExcelTitleDTO();
            userPaperExcelTitle.setPaperName(exportGroupPaperDO.getPaperName());
            return userPaperExcelTitle;
        }).collect(Collectors.toList());
        groupUserExcelTitle.setUserPaperExcelTitleList(userPaperExcelTitleList);

        return groupUserExcelTitle;

    }

    /**
     * 获取班级学员导出信息
     *
     * @param req ExportGroupUsersReq
     * @return 班级学员导出信息
     */
    private List<GroupUserInfoDTO> queryGroupUsers(ExportGroupUsersReq req) {
        List<GroupUserInfoDTO> groupUserInfos = new ArrayList<>();
        //1.参数校验
        if (Objects.isNull(req) || StringUtils.isEmpty(req.getGroupId())) {
            logger.error("export group users req is null");
            return groupUserInfos;
        }
        //2.查询班级已推送的所有试卷
        List<ExportGroupPaperDO> exportGroupPaperDOS = groupPaperMapper.selectExportGroupPapersByGroupId(req.getGroupId());
        logger.debug("query exportGroupPaperDOS are {}", exportGroupPaperDOS);
        if (CollectionUtils.isEmpty(exportGroupPaperDOS)) {
            return groupUserInfos;
        }

        //3.查询班级中所有的学员
        List<ExportGroupUserDO> exportGroupUserDOS = groupUserMapper.selectGroupUserForExportByGroupId(req.getGroupId());
        logger.debug("query exportGroupUserDOS are {}", exportGroupUserDOS);
        if (CollectionUtils.isEmpty(exportGroupUserDOS)) {
            return groupUserInfos;
        }

        //4.查询班级中所有学员所有试卷集合
        List<ExportGroupUserPaperResultDO> exportGroupUserPaperResultDOS = groupUserMapper.selectUserPaperResultsByGroupId(req.getGroupId());
        logger.debug("query exportGroupUserPaperResultDOS are {}", exportGroupUserPaperResultDOS);

        //4.封装学员对应的考试成绩
        if (CollectionUtils.isEmpty(exportGroupUserPaperResultDOS)) {
            groupUserInfos = exportGroupUserDOS.stream().filter(Objects::nonNull).map((groupUser) -> {
                // 构建每个学员的考试信息
                return buildGroupUserInfoDTOWithoutUserPaperResults(exportGroupPaperDOS, groupUser);
            }).collect(Collectors.toList());
            logger.debug("after groupUserInfos are {}", groupUserInfos);
            return groupUserInfos;
        }

        Map<String, List<ExportGroupUserPaperResultDO>> groupUserPaperMap = exportGroupUserPaperResultDOS.stream().collect(Collectors.groupingBy(ExportGroupUserPaperResultDO::getUserId));
        groupUserInfos = exportGroupUserDOS.stream().filter(Objects::nonNull).map((groupUser) -> {
            // 构建每个学员的考试信息
            return buildGroupUserInfoDTOWithUserPaperResults(exportGroupPaperDOS, groupUserPaperMap, groupUser);

        }).collect(Collectors.toList());
        logger.debug("after groupUserInfos are {}", groupUserInfos);
        return groupUserInfos;
    }

    private GroupUserInfoDTO buildGroupUserInfoDTOWithUserPaperResults(List<ExportGroupPaperDO> exportGroupPaperDOS, Map<String, List<ExportGroupUserPaperResultDO>> groupUserPaperMap, ExportGroupUserDO groupUser) {
        GroupUserInfoDTO groupUserInfoDTO = new GroupUserInfoDTO();
        groupUserInfoDTO.setAssistantName(groupUser.getAssistantName());
        groupUserInfoDTO.setOrderNum(StringUtil.valueOf(groupUser.getOrderNum()));
        groupUserInfoDTO.setStudentName(groupUser.getStudentName());

        // 构建每个学员的考试成绩集合
        List<ExportGroupUserPaperResultDO> exportGroupUserPaperResults = groupUserPaperMap.get(groupUser.getUserId());
        List<UserPaperResultDTO> userPaperResultList = new ArrayList<>();
        if (CollectionUtils.isEmpty(exportGroupUserPaperResults)) {
            exportGroupPaperDOS.forEach(e -> userPaperResultList.add(new UserPaperResultDTO(e.getPaperName())));
        } else {
            Map<String, List<ExportGroupUserPaperResultDO>> eGroupUserPaperResultMap = exportGroupUserPaperResults.stream().collect(Collectors.groupingBy(ExportGroupUserPaperResultDO::getPaperId));
            exportGroupPaperDOS.forEach(e -> {
                UserPaperResultDTO userPaperResultDTO =
                        buildUserPaperResultDTO(eGroupUserPaperResultMap, e);

                userPaperResultList.add(userPaperResultDTO);
            });
        }
        groupUserInfoDTO.setUserPaperResultList(userPaperResultList);
        return groupUserInfoDTO;
    }

    private GroupUserInfoDTO buildGroupUserInfoDTOWithoutUserPaperResults(List<ExportGroupPaperDO> exportGroupPaperDOS, ExportGroupUserDO groupUser) {
        GroupUserInfoDTO groupUserInfoDTO = new GroupUserInfoDTO();
        groupUserInfoDTO.setAssistantName(groupUser.getAssistantName());
        groupUserInfoDTO.setOrderNum(StringUtil.valueOf(groupUser.getOrderNum()));
        groupUserInfoDTO.setStudentName(groupUser.getStudentName());

        // 构建每个学员的考试成绩集合
        List<UserPaperResultDTO> userPaperResultList = new ArrayList<>();
        exportGroupPaperDOS.forEach(e -> userPaperResultList.add(new UserPaperResultDTO(e.getPaperName())));
        groupUserInfoDTO.setUserPaperResultList(userPaperResultList);
        return groupUserInfoDTO;
    }

    private UserPaperResultDTO buildUserPaperResultDTO(Map<String, List<ExportGroupUserPaperResultDO>> eGroupUserPaperResultMap, ExportGroupPaperDO e) {
        UserPaperResultDTO userPaperResultDTO = new UserPaperResultDTO();
        userPaperResultDTO.setPaperName(e.getPaperName());

        List<ExportGroupUserPaperResultDO> exportGroupUserPaperResult = eGroupUserPaperResultMap.get(e.getPaperId());
        if (CollectionUtils.size(exportGroupUserPaperResult) > 1) {
            logger.error("get exportGroupUserPaperResult happened wrong ,result are {}", exportGroupUserPaperResult);
        }
        if (CollectionUtils.size(exportGroupUserPaperResult) == 1) {
            ExportGroupUserPaperResultDO exportGroupUserPaperResultDO = exportGroupUserPaperResult.get(0);
            String correctDivideTotal;
            float scoreRateF;
            if (exportGroupUserPaperResultDO.getScore() == null) {
                correctDivideTotal = "0" + "/" + DigitalUtils.format(e.getTotalScore());
                scoreRateF = 0F;
            } else {
                correctDivideTotal = DigitalUtils.format(exportGroupUserPaperResultDO.getScore()) + "/" + DigitalUtils.format(e.getTotalScore());
                scoreRateF = exportGroupUserPaperResultDO.getScore() / e.getTotalScore();
            }
            userPaperResultDTO.setCorrectDivideTotal(correctDivideTotal);
            String scoreRate = DigitalUtils.calProportionPercentage(exportGroupUserPaperResultDO.getScore(), e.getTotalScore());
            userPaperResultDTO.setScoreRate(scoreRate + "%");
            userPaperResultDTO.setScoreRateF(scoreRateF);
            if (Objects.nonNull(exportGroupUserPaperResultDO.getFinishTime())) {
                userPaperResultDTO.setFinishTime(SDF.format(exportGroupUserPaperResultDO.getFinishTime()));
            }
        }
        return userPaperResultDTO;
    }


    public void exportGroupUsers(OutputStream os, ExportGroupUsersReq req) throws Exception {

        List<List<ExcelCell>> excelCells = new ArrayList<>();

        //获取标题
        GroupUserExcelTitleDTO groupUserExcelTitles = buildGroupUserExcelTitle(req);

        // 获取班级学员信息
        List<GroupUserInfoDTO> groupUserInfoDTOS = queryGroupUsers(req);
        if (CollectionUtils.isEmpty(groupUserInfoDTOS)) {

            new GroupUserExcelUtils(groupUserExcelTitles, excelCells).export(os);
        }
        // 按照助教名称排序
        logger.debug("before sorted groupUserInfos ");
        List<GroupUserInfoDTO> sortedGroupUsers = groupUserInfoDTOS.stream().sorted(Comparator.comparing(GroupUserInfoDTO::getAssistantName).reversed()).collect(Collectors.toList());
        logger.debug("after sorted groupUserInfos ");

        // 将班级学员信息封装为excel单元格
        excelCells = sortedGroupUsers.stream().map(e -> {
            List<ExcelCell> rows = new ArrayList<>();
            rows.add(new ExcelCell(e.getOrderNum()));
            rows.add(new ExcelCell(e.getStudentName()));
            rows.add(new ExcelCell(e.getAssistantName()));
            e.getUserPaperResultList().forEach(userPaper -> {
                ExcelStyle excelStyle = new ExcelStyle(userPaper.getColor());
                rows.add(new ExcelCell(userPaper.getScoreRate(), excelStyle));
                rows.add(new ExcelCell(userPaper.getCorrectDivideTotal(), excelStyle));
                rows.add(new ExcelCell(userPaper.getFinishTime(), excelStyle));
            });
            return rows;
        }).collect(Collectors.toList());
        logger.debug("after build groupUserPapers");
        new GroupUserExcelUtils(groupUserExcelTitles, excelCells).export(os);

    }
}
